#!/usr/bin/env python
#!conding:utf-8
"""
author:Johnson
date: 2017/5/18 9:24
version: v1.0
description:
    认证、鉴权
"""
import json
from flask.blueprints import Blueprint
from flask.json import jsonify
from flask_login.utils import current_user
from flask_login.utils import login_user
from flask.globals import request, session
from flask_login.utils import login_required, logout_user
from flask.helpers import url_for, flash, get_flashed_messages
from flask.templating import render_template
from werkzeug.utils import redirect

from blog import db
from blog.model import get_all, execute
from blog.model.user_model import User, Role
from blog.service.user_service import register_check
from tool import response_data, transaction
from tool.mail import send_mail

auth = Blueprint('auth_view',__name__)

@auth.before_app_request
def before_request():
    """
    在请求调用前该方法被调用
    :return:
    """
    if current_user.is_authenticated:
        current_user.ping()
        if not current_user.confirmed and request.endpoint and request.endpoint[:10] !='auth_view.'and request.endpoint !='static':
            return redirect(url_for('auth_view.unconfirmed'))

## 未验证邮件登录后显示的页面
@auth.route("/unconfirmed")
def unconfirmed():
    if current_user.is_anonymous or current_user.confirmed:
        return redirect(url_for("main_view.index"))
    else:
        return render_template('auth/unconfirmed.html',user = current_user)

@auth.route("/",methods = ['GET'])
def index():
    return redirect(url_for('auth_view.login'))

@auth.route("/login",methods = ["GET","POST"])
def login():
    if request.method == 'POST':
        email = request.values.get("email")
        password = request.values.get('password')
        remember_me = request.values.get('remember_me')
        user = User.query.filter_by(email = email).first()
        if user is not None and user.verify_password(password):
            if remember_me is None :
                remember = False
            else:
                remember = True
            login_user(user,remember)
            return redirect(request.args.get('next') or url_for('main_view.index'))
        flash("Invalid username or password")
        return render_template('auth/login.html')
    else:
        return render_template('auth/login.html')


@auth.route("/logout")
@login_required
def logout():
    """ 退出登录 """
    session['_flashes'] = []    #清空flash
    logout_user()
    flash('You have been logged out.')
    return redirect(url_for('main_view.index'))

@auth.route("/register",methods = ['GET','POST'])
@transaction
def register():
    if request.method == 'POST':
        password = request.values.get('password')
        password2 = request.values.get("password2")
        email = request.values.get('email')
        username = request.values.get('username')
        user = User(email =email,
                    username = username,
                    password = password)
        register_check(user)
        if password != password2:
            flash("两次password不一致")
        if len(get_flashed_messages())>0:
            return render_template('auth/register.html',user = user)
        db.session.add(user)
        token = user.generate_confirmation_token()
        send_mail(user.email,'Confirm Your Account','auth/email/confirm',user = user,token = token)
        flash('A confirmation email has been sent to you by email.')
        return redirect(url_for('auth_view.login'))
    else:
        return render_template('auth/register.html')

@auth.route("/confirm/<token>")
@login_required
@transaction
def confirm(token):
    """
    邮件验证
    :return:
    """
    if current_user.confirmed:
        return redirect(url_for('main_view.index'))
    if current_user.confirm(token):
        flash('You have confirmed your account. Thanks!')
    else:
        flash('The confirmation link is invalid or has expired.')
    return redirect(url_for('main_view.index'))

@auth.route("/confirm")
@login_required
def resend_confirmation():
    """
    重新发送验证邮件
    :return:
    """
    token = current_user.generate_confirmation_token()
    send_mail(current_user.email,'Confirm Your Account','auth/email/confirm',user = current_user,token = token)
    flash('A new confirmation email has been sent to you by email.')
    return redirect(url_for('main_view.index'))

## 忘记密码
@auth.route('/reset/password',methods = ['GET',"POST"])
def forget_password():
    pass

## 重置密码
@auth.route("/change/password",methods = ['GET','POST'])
@login_required
@transaction
def change_password():
    if request.method == 'POST':
        old_password = request.values.get('old_password')
        password = request.values.get('password')
        password2 = request.values.get('password2')
        if not current_user.verify_password(old_password):
            flash('原始密码输入有误')
        if password != password2:
            flash('两次密码不相同')
        if len(get_flashed_messages())>0:
             return render_template('auth/change_password.html')
        else:
            current_user.password = password    #重置密码
            param = {"password_hash":current_user.password_hash}
            current_user.update_by_type(param)
            flash('Your passowrd has been updated.')
            return redirect(url_for('main_view.index'))
    return render_template('auth/change_password.html')



@auth.route("/list/role")
@login_required
def list_role():
    roles = get_all("select * from t_role")
    permissions = get_all("select * from t_permission")
    return render_template('auth/auth.html', roles = roles,permissions = permissions)

@auth.route("/permissions/<int:id>")
@login_required
def get_permissions_by_role_id(id):
    sql = "select * from t_role_permission where role_id = :id"
    params = {
        "id":id
    }
    list = get_all(sql,params)
    return response_data(('id','role','permission'),list)

@auth.route("/authorize",methods = ['GET','POST'])
@login_required
@transaction
def authorize():
    """
    新增授权
    :return:
    """
    role = request.values.get('role')
    permissions = request.values.getlist('permission')
    ##　删除当前权限
    execute('delete from t_role_permission where role_id = :role',{"role":role})
    ## 新增选中权限
    for item in permissions:
        execute('insert into t_role_permission(role_id,permission_id) values(:role,:permission)',{'role':role,'permission':item})
    flash("授权修改成功.")
    return redirect(url_for('.list_role'))


@auth.route('/unauthorize',methods = ["GET"])
def unauthorized():
    """
        后端鉴权不通过，跳转到无权限提示页面
    :return:
    """
    return render_template('auth/unauthorize.html')







